home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / inet.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  11KB  |  423 lines

  1. #ifndef lint
  2. static    char sccsid[] = "@(#)inet.c    1.12 88/02/08    Copyr 1986 Sun Micro";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  7.  */
  8.  
  9. /*
  10.  * Standalone IP send and receive - specific to Ethernet
  11.  * Includes ARP and Reverse ARP
  12.  */
  13. #include "machparam.h"
  14. #include "boot.h"
  15. #include "saio.h"
  16. #include "socket.h"
  17. #include "if.h"
  18. #include "if_arp.h"
  19. #include "in.h"
  20. #include "if_ether.h"
  21. #include "in_systm.h"
  22. #include "ip.h"
  23. #include "sainet.h"
  24. #include "sunromvec.h"
  25. #include "idprom.h"
  26.  
  27. #define millitime() (*romp->v_nmiclock)
  28.  
  29. struct ether_addr etherbroadcastaddr = { 
  30.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  31. };
  32.  
  33. struct arp_packet {
  34.     struct ether_header    arp_eh;
  35.     struct ether_arp    arp_ea;
  36. #define    used_size (sizeof (struct ether_header)+sizeof(struct ether_arp))
  37.     char    filler[ETHERMIN - sizeof(struct ether_arp)];
  38. };
  39.  
  40. #define WAITCNT    2    /* 4 seconds before bitching about arp/revarp */
  41.  
  42. /*
  43.  * Fetch our Ethernet address from the ID prom
  44.  */
  45. myetheraddr(ea)
  46.     struct ether_addr *ea;
  47. {
  48.     struct idprom id;
  49.  
  50.     if (idprom(IDFORM_1, &id) != IDFORM_1) {
  51.         printf("ERROR: missing or invalid ID prom\n");
  52.         return;
  53.     }
  54.     *ea = *(struct ether_addr *)id.id_ether;
  55. }
  56.  
  57. /*
  58.  * Initialize IP state
  59.  * Find out our Ethernet address and call Reverse ARP
  60.  * to find out our Internet address
  61.  * Set the ARP cache to the broadcast host
  62.  */
  63. inet_init(sip, sain, tmpbuf)
  64.     register struct saioreq *sip;
  65.     register struct sainet *sain;
  66.     char *tmpbuf;
  67. {
  68.     myetheraddr(&sain->sain_myether);
  69.     bzero((caddr_t)&sain->sain_myaddr, sizeof(struct in_addr));
  70.     bzero((caddr_t)&sain->sain_hisaddr, sizeof(struct in_addr));
  71.     sain->sain_hisether = etherbroadcastaddr;
  72.     revarp(sip, sain, tmpbuf);
  73. }
  74.  
  75.  
  76. /*
  77.  * Output an IP packet
  78.  * Cause ARP to be invoked if necessary
  79.  */
  80. ip_output(sip, buf, len, sain, tmpbuf)
  81.     register struct saioreq *sip;
  82.     caddr_t buf, tmpbuf;
  83.     short len;
  84.     register struct sainet *sain;
  85. {
  86.     register struct ether_header *eh;
  87.     register struct ip *ip;
  88.  
  89.     eh = (struct ether_header *)buf;
  90.     ip = (struct ip *)(buf + sizeof(struct ether_header));
  91.     if (bcmp((caddr_t)&ip->ip_dst,
  92.         (caddr_t)&sain->sain_hisaddr,
  93.         sizeof(struct in_addr)) != 0) {
  94.             bcopy((caddr_t)&ip->ip_dst,
  95.                 (caddr_t)&sain->sain_hisaddr,
  96.                 sizeof (struct in_addr));
  97.             arp(sip, sain, tmpbuf);
  98.     }
  99.     eh->ether_type = ETHERTYPE_IP;
  100.     eh->ether_shost = sain->sain_myether;
  101.     eh->ether_dhost = sain->sain_hisether;
  102.     /* checksum the packet */
  103.     ip->ip_sum = 0;
  104.     ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip));
  105.     if (len < ETHERMIN + sizeof(struct ether_header)) {
  106.         len = ETHERMIN+sizeof(struct ether_header);
  107.     }
  108.     return (romp->v_xmit_packet)(buf, len);
  109. }
  110.  
  111. /*
  112.  * Check incoming packets for IP packets
  113.  * addressed to us. Also, respond to ARP packets
  114.  * that wish to know about us.
  115.  * Returns a length for any IP packet addressed to us, 0 otherwise.
  116.  */
  117. ip_input(sip, buf, sain)
  118.     register struct saioreq *sip;
  119.     caddr_t buf;
  120.     register struct sainet *sain;
  121. {
  122.     register short len;
  123.     register struct ether_header *eh;
  124.     register struct ip *ip;
  125.     register struct ether_arp *ea;
  126.  
  127.     len = (romp->v_poll_packet)( buf);
  128.     eh = (struct ether_header *)buf;
  129.     if (eh->ether_type == ETHERTYPE_IP &&
  130.         len >= sizeof(struct ether_header)+sizeof(struct ip)) {
  131.         ip = (struct ip *)(buf + sizeof(struct ether_header));
  132. #ifdef NOREVARP
  133.         if ((sain->sain_hisaddr.s_addr & 0xFF000000) == 0 &&
  134.             bcmp((caddr_t)ðerbroadcastaddr,
  135.             (caddr_t)&eh->ether_dhost,
  136.             sizeof(struct ether_addr)) != 0 &&
  137.             (in_broadaddr(sain->sain_hisaddr) ||
  138.             in_lnaof(ip->ip_src) == in_lnaof(sain->sain_hisaddr))) {
  139.             sain->sain_myaddr = ip->ip_dst;
  140.             sain->sain_hisaddr = ip->ip_src;
  141.             sain->sain_hisether = eh->ether_shost;
  142.         }
  143. #endif
  144.         if (bcmp((caddr_t)&ip->ip_dst,
  145.             (caddr_t)&sain->sain_myaddr,
  146.             sizeof(struct in_addr)) != 0)
  147.             return (0);
  148.         return (len);
  149.     }
  150.     if (eh->ether_type == ETHERTYPE_ARP &&
  151.         len >= sizeof(struct ether_header) + sizeof(struct ether_arp)) {
  152.         ea = (struct ether_arp *)(buf + sizeof(struct ether_header));
  153.         if (ea->arp_pro != ETHERTYPE_IP)
  154.             return (0);
  155.         if (bcmp((caddr_t)ea->arp_spa,
  156.             (caddr_t)&sain->sain_hisaddr,
  157.             sizeof(struct in_addr)) == 0)
  158.             sain->sain_hisether = ea->arp_sha;
  159.         if (ea->arp_op == ARPOP_REQUEST &&
  160.             (bcmp((caddr_t)ea->arp_tpa,
  161.               (caddr_t)&sain->sain_myaddr,
  162.               sizeof(struct in_addr)) == 0)) {
  163.             ea->arp_op = ARPOP_REPLY;
  164.             eh->ether_dhost = ea->arp_sha;
  165.             eh->ether_shost = sain->sain_myether;
  166.             ea->arp_tha = ea->arp_sha;
  167.             bcopy((caddr_t)ea->arp_spa,
  168.                 (caddr_t)ea->arp_tpa,
  169.                 sizeof(ea->arp_tpa));
  170.             ea->arp_sha = sain->sain_myether;
  171.             bcopy((caddr_t)&sain->sain_myaddr,
  172.                 (caddr_t)ea->arp_spa,
  173.                 sizeof(ea->arp_spa));
  174.             (romp->v_xmit_packet)(buf, 
  175.                         sizeof(struct arp_packet));
  176.         }
  177.         return (0);
  178.     }
  179.     return (0);
  180. }
  181.  
  182. /*
  183.  * arp
  184.  * Broadcasts to determine Ethernet address given IP address
  185.  * See RFC 826
  186.  */
  187. arp(sip, sain, tmpbuf)
  188.     register struct saioreq *sip;
  189.     register struct sainet *sain;
  190.     char *tmpbuf;
  191. {
  192.     struct arp_packet out;
  193.  
  194.     if (in_broadaddr(sain->sain_hisaddr)
  195. #ifdef NOREVARP
  196.         || (sain->sain_hisaddr.s_addr & 0xFF000000) == 0
  197. #endif
  198.         ) {
  199.         sain->sain_hisether = etherbroadcastaddr;
  200.         return;
  201.     }
  202.     out.arp_eh.ether_type = ETHERTYPE_ARP;
  203.     out.arp_ea.arp_op = ARPOP_REQUEST;
  204.     out.arp_ea.arp_tha = etherbroadcastaddr;    /* what we want */
  205.     bcopy((caddr_t)&sain->sain_hisaddr,
  206.         (caddr_t)out.arp_ea.arp_tpa,
  207.         sizeof(sain->sain_hisaddr));
  208.     comarp(sip, sain, &out, tmpbuf);
  209. }
  210.  
  211. /*
  212.  * Reverse ARP client side
  213.  * Determine our Internet address given our Ethernet address
  214.  * See RFC 903
  215.  */
  216. revarp(sip, sain, tmpbuf)
  217.     register struct saioreq *sip;
  218.     register struct sainet *sain;
  219.     char *tmpbuf;
  220. {
  221.     struct arp_packet out;
  222.  
  223. #ifdef NOREVARP
  224.     bzero((caddr_t)&sain->sain_myaddr, sizeof(struct in_addr));
  225.     bcopy((caddr_t)&sain->sain_myether.ether_addr_octet[3],
  226.         (caddr_t)(&sain->sain_myaddr)+1, 3);
  227. #else
  228.     out.arp_eh.ether_type = ETHERTYPE_REVARP;
  229.     out.arp_ea.arp_op = REVARP_REQUEST;
  230.     out.arp_ea.arp_tha = sain->sain_myether;
  231.     /* What we want to find out... */
  232.     bzero(out.arp_ea.arp_tpa, sizeof(struct in_addr));
  233.     comarp(sip, sain, &out, tmpbuf);
  234. #endif
  235. }
  236.  
  237. /*
  238.  * Common ARP code 
  239.  * Broadcast the packet and wait for the right response.
  240.  * Fills in *sain with the results
  241.  */
  242. comarp(sip, sain, out, tmpbuf)
  243.     register struct saioreq *sip;
  244.     register struct sainet *sain;
  245.     register struct arp_packet *out;
  246.     char *tmpbuf;
  247. {
  248.     register struct arp_packet *in = (struct arp_packet *)tmpbuf;
  249.     register int e, count, time, feedback,len, delay = 2;
  250.     char    *ind = "-\|/";
  251.     struct in_addr tmp_ia;
  252.  
  253.     out->arp_eh.ether_dhost = etherbroadcastaddr;
  254.     out->arp_eh.ether_shost = sain->sain_myether;
  255.     out->arp_ea.arp_hrd =  ARPHRD_ETHER;
  256.     out->arp_ea.arp_pro = ETHERTYPE_IP;
  257.     out->arp_ea.arp_hln = sizeof(struct ether_addr);
  258.     out->arp_ea.arp_pln = sizeof(struct in_addr);
  259.     out->arp_ea.arp_sha = sain->sain_myether;
  260.     bcopy((caddr_t)&sain->sain_myaddr,
  261.         (caddr_t)out->arp_ea.arp_spa, 
  262.         sizeof(out->arp_ea.arp_spa));
  263.     feedback = 0;
  264.  
  265.     for (count=0; ; count++) {
  266.         if (count == WAITCNT) {
  267.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  268.                 printf("\nRequesting Ethernet address for ");
  269.                 bcopy((caddr_t)out->arp_ea.arp_tpa,
  270.                     (caddr_t)&tmp_ia, sizeof(tmp_ia));
  271.                 inet_print(tmp_ia);
  272.             } else {
  273.                 printf("\nRequesting Internet address for ");
  274.                 ether_print(&out->arp_ea.arp_tha);
  275.             }
  276.         }
  277.         e = (romp->v_xmit_packet)( (caddr_t)out,
  278.             sizeof *out);
  279.         if (e)
  280.             printf("X\b");
  281.         else
  282.             printf("%c\b", ind[feedback++ % 4]); /* Show activity */
  283.  
  284.         time = millitime() + (delay * 1000);    /* broadcast delay */
  285.         while (millitime() <= time) {
  286.             len = (romp->v_poll_packet)( tmpbuf);
  287.             if (len < used_size)
  288.                 continue;
  289.             if (in->arp_ea.arp_pro != ETHERTYPE_IP)
  290.                 continue;
  291.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  292.                 if (in->arp_eh.ether_type != ETHERTYPE_ARP)
  293.                     continue;
  294.                 if (in->arp_ea.arp_op != ARPOP_REPLY)
  295.                     continue;
  296.                 if (bcmp((caddr_t)in->arp_ea.arp_spa,
  297.                     (caddr_t)out->arp_ea.arp_tpa,
  298.                      sizeof(struct in_addr)) != 0)
  299.                     continue;
  300.                 if (count >= WAITCNT) {
  301.                     printf("Found at ");
  302.                     ether_print(&in->arp_ea.arp_sha);
  303.                 }
  304.                 sain->sain_hisether = in->arp_ea.arp_sha;
  305.                 return;
  306.             } else {        /* Reverse ARP */
  307.                 if (in->arp_eh.ether_type !=ETHERTYPE_REVARP)
  308.                     continue;
  309.                 if (in->arp_ea.arp_op != REVARP_REPLY)
  310.                     continue;
  311.                 if (bcmp((caddr_t)&in->arp_ea.arp_tha,
  312.                     (caddr_t)&out->arp_ea.arp_tha, 
  313.                     sizeof (struct ether_addr)) != 0)
  314.                     continue;
  315.  
  316.                 if (count >= WAITCNT) {
  317.                     printf("Internet address is ");
  318.                     bcopy((caddr_t)in->arp_ea.arp_tpa,
  319.                         (caddr_t)&tmp_ia, sizeof(tmp_ia));
  320.                     inet_print(tmp_ia);
  321.                 }
  322.                 bcopy((caddr_t)in->arp_ea.arp_tpa, 
  323.                     (caddr_t)&sain->sain_myaddr,
  324.                     sizeof(sain->sain_myaddr));
  325.                 /*
  326.                  * short circuit first ARP
  327.                  */
  328.                 bcopy((caddr_t)in->arp_ea.arp_spa, 
  329.                     (caddr_t)&sain->sain_hisaddr,
  330.                     sizeof(sain->sain_hisaddr));
  331.                 sain->sain_hisether = in->arp_ea.arp_sha;
  332.                 return;
  333.             }
  334.         }
  335.  
  336.         delay = delay * 2;    /* Double the request delay */
  337.         if (delay > 64)        /* maximum delay is 64 seconds */
  338.             delay = 64;
  339.  
  340.         (*sip->si_sif->sif_reset)(sip->si_devdata);
  341.     }
  342.     /* NOTREACHED */
  343. }
  344.  
  345. /*
  346.  * Return the host portion of an internet address.
  347.  */
  348. in_lnaof(in)
  349.     struct in_addr in;
  350. {
  351.     register u_long i = ntohl(in.s_addr);
  352.  
  353.     if (IN_CLASSA(i))
  354.         return ((i)&IN_CLASSA_HOST);
  355.     else if (IN_CLASSB(i))
  356.         return ((i)&IN_CLASSB_HOST);
  357.     else
  358.         return ((i)&IN_CLASSC_HOST);
  359. }
  360.  
  361. /*
  362.  * Test for broadcast IP address
  363.  */
  364. in_broadaddr(in)
  365.     struct in_addr in;
  366. {
  367.     register u_long i = ntohl(in.s_addr);
  368.  
  369.     if (IN_CLASSA(i)) {
  370.         i &= IN_CLASSA_HOST;
  371.         return (i == 0 || i == 0xFFFFFF);
  372.     } else if (IN_CLASSB(i)) {
  373.         i &= IN_CLASSB_HOST;
  374.         return (i == 0 || i == 0xFFFF);
  375.     } else if (IN_CLASSC(i)) {
  376.         i &= IN_CLASSC_HOST;
  377.         return (i == 0 || i == 0xFF);
  378.     } else
  379.         return (0);
  380.     /*NOTREACHED*/
  381. }
  382.  
  383. /*
  384.  * Compute one's complement checksum
  385.  * for IP packet headers 
  386.  */
  387. ipcksum(cp, count)
  388.     caddr_t    cp;
  389.     register unsigned short    count;
  390. {
  391.     register unsigned short    *sp = (unsigned short *)cp;
  392.     register unsigned long    sum = 0;
  393.     register unsigned long    oneword = 0x00010000;
  394.  
  395.     count >>= 1;
  396.     while (count--) {
  397.         sum += *sp++;
  398.         if (sum >= oneword) {        /* Wrap carries into low bit */
  399.             sum -= oneword;
  400.             sum++;
  401.         }
  402.     }
  403.     return (~sum);
  404. }
  405.  
  406. inet_print(s)
  407.     struct in_addr s;
  408. {
  409.     printf("%d.%d.%d.%d\n",
  410.         (s.s_addr >> 24) & 0xff,
  411.         (s.s_addr >> 16) & 0xff,
  412.         (s.s_addr >>  8) & 0xff,
  413.         s.s_addr & 0xff);
  414. }
  415.  
  416. ether_print(ea)
  417.     struct ether_addr *ea;
  418. {
  419.     register u_char *p = &ea->ether_addr_octet[0];
  420.  
  421.     printf("%x:%x:%x:%x:%x:%x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
  422. }
  423.